Repository navigation
Fail instead of silently dropping Plutus scripts the era does not support - #1363
Merged
Merged
Conversation
carbolymer
added this pull request to stack #1364
September 30, 2026 13:48
4 tasks done
carbolymer
force-pushed
the
mgalazyn/fix/unsupported-plutus-language-error
branch
2 times, most recently
from
October 1, 2026 19:25
1c03d44 to
ed67933
Compare
carbolymer
force-pushed
the
mgalazyn/fix/unsupported-plutus-language-error
branch
from
October 1, 2026 20:13
ed67933 to
62d4680
Compare
carbolymer
marked this pull request as ready for review
October 1, 2026 20:13
carbolymer
requested review from
a team,
CarlosLopezDeLara,
Jimbo4350,
disassembler,
erikd and
palas
as code owners
October 1, 2026 20:13
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The dependency bump is misclassified and the experimental API migration note inaccurately describes two previous return types.
Review effort: Balanced
Findings: 3
Open (3)
What changed in this PR
Prevents unsupported Plutus scripts from being silently omitted during transaction construction.
Changes:
- Returns explicit errors for unsupported witness and reference-script languages.
- Adds regression tests, V4 fixtures, and golden output.
- Updates Plutus dependencies and changelog fragments.
| File | Description |
|---|---|
flake.lock |
Updates the CHaP revision. |
cardano-api/test/cardano-api-test/Test/Cardano/Api/Transaction/Body/Plutus/Scripts.hs |
Adds unsupported-language regression tests. |
cardano-api/test/cardano-api-golden/Test/Golden/ErrorsSpec.hs |
Adds the new output-error golden case. |
cardano-api/test/cardano-api-golden/files/errors/Cardano.Api.Tx.Body.TxBodyError/TxBodyOutputReferenceScriptLanguageNotSupportedInEra.txt |
Records the new error message. |
cardano-api/src/Cardano/Api/Tx/Internal/Output.hs |
Validates output reference-script languages. |
cardano-api/src/Cardano/Api/Tx/Internal/Body.hs |
Applies validation during body creation. |
cardano-api/src/Cardano/Api/Experimental/Tx/Internal/TxScriptWitnessRequirements.hs |
Propagates unsupported-language failures. |
cardano-api/src/Cardano/Api/Experimental/Tx/Internal/BodyContent/New.hs |
Adds and returns the unsigned-transaction error. |
cardano-api/src/Cardano/Api/Experimental/Tx/Internal/AnyWitness.hs |
Changes script extraction to Either. |
cardano-api/src/Cardano/Api/Experimental/Plutus/Internal/Shim/LegacyScripts.hs |
Adapts legacy witness conversion. |
cardano-api/src/Cardano/Api/Experimental/AnyScriptWitness.hs |
Detects unsupported inline script languages. |
cardano-api/gen/Test/Gen/Cardano/Api/Typed.hs |
Restricts generation to supported languages. |
cardano-api/gen/Test/Gen/Cardano/Api/Hardcoded.hs |
Adds Plutus V4 fixtures. |
cardano-api/cardano-api.cabal |
Requires Plutus 1.71 dependencies. |
cabal.project |
Advances the CHaP index state. |
.changes/plutus-1-71-bump.yml |
Documents the dependency bump. |
.changes/legacy-tx-body-unsupported-reference-script-language-error.yml |
Documents the legacy API break. |
.changes/experimental-tx-unsupported-plutus-language-error.yml |
Documents the experimental API break. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| description: | | ||
| `makeUnsignedTx` now fails with `MakeUnsignedTxPlutusLanguageNotSupportedInEra` when an inline Plutus script uses a language the era does not support. | ||
| Before, the script was silently dropped from the witness set while its redeemer was kept, so the transaction failed on submission. | ||
| `getAnyWitnessScript`, `getAnyPlutusWitnessPlutusScript`, `getTxScriptWitnessRequirements` and `getTxScriptWitnessesRequirements` now return `Either L.Language` instead of `Maybe`. |
Comment on lines
+228
to
+229
| -- | An inline Plutus witness must be rejected, not silently dropped with its | ||
| -- redeemer, when the era does not support its language. V4 fails in Conway. |
Contributor
|
What about this approach? master...jordan/plutus-language-in-era-vs-master |
carbolymer
force-pushed
the
mgalazyn/fix/unsupported-plutus-language-error
branch
2 times, most recently
from
October 7, 2026 13:33
4f7d365 to
b2764fd
Compare
3 of 4 tasks
carbolymer
force-pushed
the
mgalazyn/fix/unsupported-plutus-language-error
branch
4 times, most recently
from
October 8, 2026 13:50
54a1fbb to
5f5de62
Compare
Jimbo4350
approved these changes
Oct 8, 2026
Jimbo4350
left a comment
Contributor
There was a problem hiding this comment.
LGTM. I have one further small simplification to suggest: mgalazyn/fix/unsupported-plutus-language-error...jordan/plutus-script-in-era-single-field
carbolymer
force-pushed
the
mgalazyn/fix/unsupported-plutus-language-error
branch
from
October 9, 2026 06:29
5f5de62 to
1833ae9
Compare
…port Plutus scripts in a language the era does not support are rejected instead of being dropped. In the experimental API the check happens where the bytes enter. decodeAnyPlutusScript and deserialiseAnyPlutusScriptFromTextEnvelope fail with a decoder error that names the language and the era. PlutusScriptInEra carries the ledger's EraPlutusTxInfo lang era evidence in its constructor, so it exists only for a pairing the ledger supports and converts to the ledger script through mkSupportedPlutusScript without a partial step. deserialisePlutusScriptInEra and deserialiseAnyPlutusScriptOfLanguage take that constraint instead of a language singleton, and so do the SerialiseAsCBOR and HasTextEnvelope instances of PlutusScriptInEra. PlutusLangInEra lang era is the runtime proof, returned by plutusLangInShelleyBasedEra and plutusLangInEra, which ask the ledger's mkSupportedLanguage; cardano-api keeps no table of languages per era. The legacy shim looks the language up at runtime, and the Either L.Language results and MakeUnsignedTxPlutusLanguageNotSupportedInEra are gone. In the legacy API, createTransactionBody fails with TxOutputReferenceScriptLanguageNotSupportedInEra when an output or the return collateral carries a reference script in a language the era does not support. Before, the output was built without the script and no error was reported. The test generators take the supported Plutus languages from scriptLanguageSupportedInEra, and the Plutus V4 fixture is a validator compiled against Plutus V4. Co-authored-by: Jordan Millar <jordan.millar@iohk.io>
carbolymer
force-pushed
the
mgalazyn/fix/unsupported-plutus-language-error
branch
from
October 9, 2026 06:30
1833ae9 to
cfcc6e2
Compare
Contributor
Author
|
@Jimbo4350 makes sense, thanks! I've used it 👍🏻 |
carbolymer
added a commit
that referenced
this pull request
Oct 9, 2026
…lutus-language-error Fail instead of silently dropping Plutus scripts the era does not support
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Plutus scripts in a language the era does not support are rejected instead of being dropped.
In the experimental API the check happens where the bytes enter.
decodeAnyPlutusScriptanddeserialiseAnyPlutusScriptFromTextEnvelopefail with a decoder error that names the language and the era.PlutusScriptInEracan only be built for a pairing the ledger supports:mkPlutusScriptInEra,deserialisePlutusScriptInEraanddeserialiseAnyPlutusScriptOfLanguagetake the ledger'sEraPlutusTxInfo lang eraconstraint, and so do itsSerialiseAsCBORandHasTextEnvelopeinstances, so a wrong pairing is a compile error.PlutusLangInEra lang erais the runtime proof returned byplutusLangInShelleyBasedEraandplutusLangInEra, which ask the ledger'smkSupportedLanguage; cardano-api keeps no table of languages per era.PlutusScriptInEraalso holds the ledger script, built once through the ledger'smkSupportedPlutusScript, so no later conversion can fail andfromPlutusRunnableis gone.This is a breaking change to the experimental API:
PlutusScriptInEragains a field and a constraint,deserialisePlutusScriptInEraanddeserialiseAnyPlutusScriptOfLanguagelose their language argument, anddecodeAnyPlutusScriptanddeserialiseAnyPlutusScriptFromTextEnvelopenow requireIsShelleyBasedErafor the api era that matches the ledger era.In the legacy API,
createTransactionBodyfails withTxOutputReferenceScriptLanguageNotSupportedInErawhen an output or the return collateral carries a reference script in a language the era does not support.The test generators take the supported Plutus languages from
scriptLanguageSupportedInEra, and the Plutus V4 fixture is a validator compiled against Plutus V4.Context
The experimental part follows the design Jordan proposed on this PR and prepared in PR 1372, folded in here:
Known gap, outside this PR:
eraMaxLanguage, still PlutusV3, so a PlutusV4 auxiliary script in Dijkstra is dropped on read-back until ledger 0.5.0.0. A TODO marks the spot intoAuxiliaryData.eraMaxLanguagetoPlutusV4, fix tests cardano-ledger#6109How to trust this PR
prop_deserialise_rejects_unsupported_plutus_languagechecks that V4 bytes fail to decode in Conway with the error naming the era.prop_makeUnsignedTx_accepts_reference_plutus_v4_witnesschecks that a reference witness still passes.prop_createTransactionBody_rejects_unsupported_reference_script_languagechecks the legacy reference script path.A test that builds a Plutus V4 inline witness in Conway no longer typechecks, which is the point of the change.
Checklist